+function ($) {
    $.expr[":"].searchSelectContains = $.expr.createPseudo(function (arg) {
        return function (elem) {
            if ($(elem).children('a').attr('data-simplified') !== undefined) {
                return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0 || $(elem).children('a').attr('data-simplified').toUpperCase().indexOf(arg.toUpperCase()) >= 0;
            } else {
                return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
            }
        };
    });

    $.fn.inputSelect = function (options, downBack, selectBack, initBack) {
        var defaultsettings = {
            isFilter: true,
            defaultText: '-请选择-',
            isInputEnabled: false,
            onInputBlur: null,
            jsonData: null,
            initialValue: null,
            jsonDataId: null,
            jsonDataText: null,
            jsonSimplifiedKey: null,
            ajax: {
                url: null,
                data: null,
                dataType: null,
                resultKey: null,
                type: null,
                beforeSend: null,
                error: null,
                success: null,
                complete: null
            },
            itemVisible: 5
        };

        if (this.length == 0)
            return this;
        if (this.length > 1) {
            this.each(function () {
                $(this).inputSelect(options, downBack, selectBack, initBack);
            });
            return this;
        }

        var $this = this,
                selectedInput = $this.find('.cus-sel-chosed').find('input'),
                selectedText = $this.find('.cus-sel-chosed').find('.cus-sel-chosed-txt'),
                _data = downBack,
                setKey = {},
                setVal = {},
                getData = {},
                opts = $.extend({}, defaultsettings, options),
                tempStr = '';

        $this.attr({'data-defaulttext': opts.defaultText});
        $this.find('.cus-sel-list').height(37 * opts.itemVisible);

        function setCurr(v) {
            if ($this.find('a[data-value="' + v.key + '"]').length <= 0) {
                return false;
            }

            setChosedKeyVal(v.key, v.val);
            $this.find('.cus-sel-list').find('a').removeClass('hover');
            $this.find('.cus-sel-list').find('a[data-value="' + v.key + '"]').addClass('hover');
        }

        function isString(value) {
            return Object.prototype.toString.call(value) === "[object String]";
        }

        function isArrayFn(value) {
            if (typeof Array.isArray === "function") {
                return Array.isArray(value);
            } else {
                return Object.prototype.toString.call(value) === "[object Array]";
            }
        }

        function isFunction(value) {
            return Object.prototype.toString.call(value) === '[object Function]';
        }
        ;

        function render(data, jsonDataId, jsonDataText, jsonSimplifiedKey) {
            var i,
                    dataLength,
                    tempStr = '';

            if (isArrayFn(data)) {
                for (i = 0, dataLength = data.length; i < dataLength; i++) {
                    // if(isArrayFn(data[i])) {
                    //     tempStr += render(data[i]);
                    // } else {
                    if (jsonDataId && jsonDataText) {
                        if (jsonSimplifiedKey) {
                            if (data[i][jsonDataId] === '' || data[i][jsonDataId] <= 0) {
                                tempStr = '<li><a href="javascript:;" title="' + data[i][jsonDataText] + '" data-value="' + data[i][jsonDataId] + '" data-simplified="' + data[i][jsonSimplifiedKey] + '">' + data[i][jsonDataText] + '</a></li>' + tempStr;
                            } else {
                                tempStr += '<li><a href="javascript:;" title="' + data[i][jsonDataText] + '" data-value="' + data[i][jsonDataId] + '" data-simplified="' + data[i][jsonSimplifiedKey] + '">' + data[i][jsonDataText] + '</a></li>';
                            }
                        } else {
                            if (data[i][jsonDataId] === '' || data[i][jsonDataId] <= 0) {
                                tempStr = '<li><a href="javascript:;" title="' + data[i][jsonDataText] + '" data-value="' + data[i][jsonDataId] + '">' + data[i][jsonDataText] + '</a></li>' + tempStr;
                            } else {
                                tempStr += '<li><a href="javascript:;" title="' + data[i][jsonDataText] + '" data-value="' + data[i][jsonDataId] + '">' + data[i][jsonDataText] + '</a></li>';
                            }
                        }
                    } else {
                        for (var key in data[i]) {
                            if (key === '' || key <= 0) {
                                tempStr = '<li><a href="javascript:;" title="' + data[i][key] + '" data-value="' + key + '">' + data[i][key] + '</a></li>' + tempStr;
                            } else {
                                tempStr += '<li><a href="javascript:;" title="' + data[i][key] + '" data-value="' + key + '">' + data[i][key] + '</a></li>';
                            }
                        }
                    }
                    // }
                }
            }
            return tempStr;
        }

        function setInitialValue(initialValue, jsonDataArr) {
            var tempKey,
                    tempVal;
            if (initialValue) {
                if (initialValue.key == undefined && initialValue.val == undefined) {
                    for (var key in initialValue) {
                        tempKey = key,
                                tempVal = initialValue[key];

                        setChosedKeyVal(tempKey, tempVal);
                        $this.find('.cus-sel-list').find('a[data-value="' + tempKey + '"]').addClass('hover');
                    }
                } else if (initialValue.key != undefined && initialValue.val != undefined) {
                    tempKey = initialValue.key,
                            tempVal = initialValue.val;

                    setChosedKeyVal(tempKey, tempVal);
                    $this.find('.cus-sel-list').find('a[data-value="' + tempKey + '"]').addClass('hover');
                } else if (initialValue.key != undefined) {
                    tempKey = initialValue.key;
                    tempVal = $this.find('.cus-sel-list').find('a[data-value="' + tempKey + '"]').addClass('hover').text();

                    setChosedKeyVal(tempKey, tempVal);
                } else if (initialValue.val != undefined) {
                    tempVal = initialValue.val;
                    tempKey = $this.find('.cus-sel-list').find('a[title="' + tempVal + '"]').addClass('hover').attr('data-value');

                    setChosedKeyVal(tempKey, tempVal);
                }

                if (selectBack) {
                    selectBack($this, tempVal, tempKey);
                }
            } else {
                setChosedKeyVal('', $this.attr('data-defaulttext'));
            }
        }

        function scrollToSelectedItem(selectedItem, scrollContainer) {
            if (selectedItem.outerHeight() + selectedItem.position().top > scrollContainer.height()) {
                scrollContainer.scrollTop(scrollContainer.scrollTop() + selectedItem.outerHeight() + selectedItem.position().top - scrollContainer.height());
            } else if (selectedItem.position().top < 0) {
                scrollContainer.scrollTop(scrollContainer.scrollTop() + selectedItem.position().top);
            }
        }

        function showList($Obj, downBack) {
            if ($Obj) {
                $Obj.addClass('active').css({zIndex: 1000});
                var bodyScrollTop = document.documentElement.scrollTop + document.body.scrollTop,
                        domTop = $Obj.offset().top,
                        bodyHeight = $(window).height(),
                        listHeight = $Obj.children('.cus-sel-list').outerHeight(true),
                        chosedHeight = $Obj.outerHeight(true);

                if (-(domTop + chosedHeight - bodyScrollTop - bodyHeight) < listHeight) {
                    $Obj.children('.cus-sel-list').show().css({'top': -(listHeight) + 'px'});
                } else {
                    $Obj.children('.cus-sel-list').show().css({'top': chosedHeight + 'px'});
                }
                if (downBack && isFunction(downBack)) {
                    downBack($Obj);
                }
            }
        }

        function hideList() {
            $this.find('.cus-sel-list').hide();
            $this.css({zIndex: 1});
        }

        function selectItem($Obj, selectBack) {
            var key,
                    value;

            if ($Obj) {
                value = $Obj.text(),
                        key = $Obj.attr('data-value');

                $this.attr('value', key).removeClass('active').find('.cus-sel-list').find('a').removeClass('hover');
                $Obj.addClass('hover');
                setChosedKeyVal(key, value);

                if (selectBack) {
                    selectBack($this, value, key);
                }
            }
        }

        function filterList(filterText) {
            //过滤文本时清除下拉数据的选中状态，清除当前对象value值/选中文本的data-value
            $this.children('.cus-sel-list').find('.hover').removeClass('hover');
            $this.attr('value', '').children('.cus-sel-chosed')
                    .find('.cus-sel-chosed-txt').text('').attr('data-value', '').end()
                    .find('input').attr('data-value', '');

            var filterText = $.trim(filterText);

            if (filterText) {
                $this.children('.cus-sel-list').find('li').show().end().find('li:not(:searchSelectContains(' + filterText + '))').hide();

                return $this.children('.cus-sel-list').find('li:searchSelectContains(' + filterText + ')');
            } else {
                $this.children('.cus-sel-list').find('li').show();

                return $this.children('.cus-sel-list').find('li');
            }
        }

        function setChosedKeyVal(key, value) {
            $this.attr('value', key);
            selectedInput.val(value).attr('data-value', key);
            selectedText.text(value).attr('data-value', key);
        }

        // isInputEnabled为true，显示文本框
        if (opts.isInputEnabled) {
            if ($this.data('bind')) {
                selectedInput.off('.cusSel');
            } else {
                $this.data('bind', true);
            }

            selectedText.hide();
            setChosedKeyVal('', $this.attr('data-defaulttext'));
            selectedInput.addClass('cus-sel-chosed-input').on('keydown.cusSel', function (event) {
                event.stopPropagation();

                var liVisible = $this.children('.cus-sel-list').find('li:visible'),
                        selectedItem = $this.children('.cus-sel-list').find('.hover').eq(0),
                        selectedItemIndex = liVisible.index(selectedItem.parent());

                if (event.which === 13) {         //enter
                    event.preventDefault();
                    if (selectedItem) {
                        selectItem(selectedItem, selectBack);
                    } else {
                        setChosedKeyVal('', $this.attr('data-defaulttext'));
                    }
                    hideList();
                } else if (event.which == 27) { //ese
                } else if (event.which == 40) { //down
                    event.preventDefault();

                    if (liVisible.length > 0) {
                        if (selectedItem.parent().is(':visible')) {
                            if (liVisible.length > 1) {
                                selectedItem.removeClass('hover');

                                if (selectedItemIndex != liVisible.length - 1) {
                                    selectedItem = liVisible.eq(selectedItemIndex + 1).find('a').addClass('hover');
                                } else {
                                    selectedItem = liVisible.first().find('a').addClass('hover');
                                }
                            }
                        } else {
                            selectedItem.removeClass('hover');
                            selectedItem = liVisible.eq(0).find('a').addClass('hover');
                        }

                        scrollToSelectedItem(selectedItem, $this.children('.cus-sel-list'));
                    }
                } else if (event.which == 38) { //up
                    event.preventDefault();

                    if (liVisible.length > 0) {
                        if (selectedItem.parent().is(':visible')) {
                            if (liVisible.length > 1) {
                                selectedItem.removeClass('hover');
                                if (selectedItemIndex != 0) {
                                    selectedItem = liVisible.eq(selectedItemIndex - 1).find('a').addClass('hover');
                                } else {
                                    selectedItem = liVisible.last().find('a').addClass('hover');
                                }
                            }
                        } else {
                            selectedItem.removeClass('hover');
                            selectedItem = liVisible.eq(0).find('a').addClass('hover');
                        }

                        scrollToSelectedItem(selectedItem, $this.children('.cus-sel-list'));
                    }
                }
            }).on('keyup.cusSel', function (event) {

                if (event.which != 13 && event.which != 27 && event.which != 38 && event.which != 40) {
                    if (opts.isFilter) {
                        var filterResult = filterList($(this).val());

                        if (filterResult.length) {
                            showList($this, downBack);
                        } else {
                            hideList();
                        }
                    }else{
                        showList($this, downBack);
                    }

                    $this.find('.cus-sel-chosed-txt').text($(this).val()).attr('data-value', $(this).attr('data-value'));
                }


            }).on('focus.cusSel', function () {
                if ($.trim($(this).val()) === $this.attr('data-defaulttext')) {
                    $(this).val('');
                }
            }).on('blur.cusSel', function () {
                var t = this;
                setTimeout(function () {
                    if ($.trim(selectedInput.val()) === '') {
                        selectedInput.val($this.attr('data-defaulttext'));
                    }
                    if (opts.onInputBlur) {
                        opts.onInputBlur(t);
                    }
                }, 100);
            });
        }

        if (isString(options)) {
            switch (options) {
                case 'setDatas':
                    setCurr(_data);
                    break;
                case 'setDataKey':
                    setKey.key = _data;
                    setKey.val = $.trim($this.find('.cus-sel-list').find('a[data-value="' + _data + '"]').text());
                    setCurr(setKey);
                    break;
                case 'setDataVal':
                    setVal.val = _data;
                    $this.find('.cus-sel-list').find('a').each(function () {
                        if ($.trim($(this).text()) == _data) {
                            setVal.key = $(this).data('value');
                        }
                    });
                    setCurr(setVal);
                    break;
                case 'getDatas':
                    getData.key = selectedText.attr('data-value');
                    getData.val = $.trim(selectedText.text()) === $this.attr('data-defaulttext') ? '' : $.trim(selectedText.text());
                    return getData;
                    break;
                case 'getDataKey':
                    return selectedText.attr('data-value');
                    break;
                case 'getDataVal':
                    return $.trim(selectedText.text()) === $this.attr('data-defaulttext') ? '' : $.trim(selectedText.text());
                    break;
                case 'resetValue':
                    setChosedKeyVal('', $this.attr('data-defaulttext'));
                    $this.find('.cus-sel-list').find('a.hover').removeClass('hover');
                    break;
                case 'clearValue':
                    setChosedKeyVal('', $this.attr('data-defaulttext'));
                    $this.find('.cus-sel-list').find('ul').html('');
                    break;
            }

            return false;
        }

        if (opts.ajax.url) {
            $.ajax({
                url: opts.ajax.url,
                data: opts.ajax.data,
                dataType: opts.ajax.datatype ? opts.ajax.datatype : 'json',
                type: opts.ajax.type ? opts.ajax.type : 'get',
                beforeSend: function (XHR) {
                    if (opts.ajax.beforeSend) {
                        opts.ajax.beforeSend.call($this, {'XHR': XHR});
                    } else {
                        return;
                    }
                },
                error: function (XHR, status, error) {
                    if (opts.ajax.error) {
                        opts.ajax.error.call($this, {'XHR': XHR, 'textStatus': status, 'errorThrown': error});
                    } else {
                        return;
                    }
                },
                complete: function (XHR, status) {
                    if (opts.ajax.complete) {
                        opts.ajax.complete.call($this, {'XHR': XHR, 'textStatus': status});
                    } else {
                        return;
                    }
                },
                success: function (data, status) {
                    var response = data,
                            ajaxResultKey = opts.ajax.resultKey,
                            tempHtml;

                    if (opts.ajax.success) {
                        opts.ajax.success.call($this, {'response': data, 'textStatus': status});
                    } else {
                        if (ajaxResultKey) {
                            tempHtml = render(response[ajaxResultKey], opts.jsonDataId, opts.jsonDataText, opts.jsonSimplifiedKey);
                            $this.children('.cus-sel-list').children('ul').html(tempHtml);
                            setInitialValue(opts.initialValue, response[ajaxResultKey]);
                        } else {
                            alert('使用ajax加载数据需配置resultKey（json数组对应的key）');
                        }
                    }


                }
            });
        }

        if (opts.jsonData) {
            tempStr = render(opts.jsonData, opts.jsonDataId, opts.jsonDataText, opts.jsonSimplifiedKey);
            $this.children('.cus-sel-list').children('ul').html(tempStr);
            setInitialValue(opts.initialValue, opts.jsonData);
        }

        if ($this.data('bind')) {
            $this.off('click.cusSel', '.cus-sel-chosed').children('.cus-sel-list').off('click.cusSel', 'a');
        } else {
            $this.data('bind', true);
        }

        $this.on('click.cusSel', '.cus-sel-chosed', function (e) {
            if ($this.is('.disabled') || $this.is('.active')) {
                return false;
            }
            $('.cus-sel').removeClass('active').css({zIndex: 1});
            $('.cus-sel-list').hide();

            var _this = $(this);

            if (opts.isInputEnabled) {
                if ($(e.target).is('.cus-sel-chosed-input')) {
                    return false;
                } else if ($(e.target).is('.jselect-icon')) {
                    showList($this, downBack);
                    selectedInput.focus();
                }
            } else {
                showList($this, downBack);
            }
        });

        $this.children('.cus-sel-list').on('click.cusSel', 'a', function () {
            var _this = $(this);

            selectItem(_this, selectBack);
            hideList();

            return false;
        });

        if (initBack) {
            setTimeout(function () {
                initBack();
            }, 300);
        }

        $this.optionsData = function (data, funback) {
            if (data) {
                tempStr = render(data, opts.jsonDataId, opts.jsonDataText, opts.jsonSimplifiedKey);
                $this.children('.cus-sel-list').children('ul').html(tempStr);
                setChosedKeyVal('', $this.attr('data-defaulttext'));
            }
            if (funback) {
                funback($this);
            }
        };

        return this;
    };


    $("html,body").click(function (e) {
        var target = e.target;
        if ($(target).parents(".cus-sel").length == 0) {
            $(".cus-sel").removeClass("active").css({zIndex: 1});
            $(".cus-sel-list").hide();
        }
    });

    $(document).on('mouseenter', '[data-toggle="inputSelect"]', function (e) {
        if ($(this).data('mouseenter'))
            return false;
        $(this).data('mouseenter', true);
        $(this).inputSelect({isInputEnabled: true});
    });

}(jQuery);